#ifndef NNE_RUNTIME_C_API_H_
#define NNE_RUNTIME_C_API_H_
#ifdef __cplusplus
extern "C" {
#endif

#define nne_status void

typedef enum
{
    None,
    Relu,
    LeakyRelu
} nne_activation_type;

typedef struct _nne_activation_param
{
    nne_activation_type type;
    float activation_detail; // for leaky relu, the value of lambda
} nne_activation_param;

typedef struct _nne_tensor
{
    unsigned int dim1;// for in/out tensor:N; for kernel tensor: O; for bias tensor:O
    unsigned int dim2;// for in/out tensor:C; for kernel tensor: I; for bias tensor:(unused)
    unsigned int dim3;// for in/out tensor:H; for kernel tensor: H; for bias tensor:(unused)
    unsigned int dim4;// for in/out tensor:W; for kernel tensor: W; for bias tensor:(unused)
    int quantize_scale;
    void *tensor_addr;
} nne_tensor;

typedef struct _nne_conv_param
{
    unsigned int kernel_size[2]; // 0:H, 1:W
    unsigned int stride[2]; // 0:H, 1:W
    unsigned int padding[4]; // 0:left, 1:right, 2:top, 3:bottom
    signed char padding_word;
	unsigned int dilations[2]; // the dilation factor for each dimension of input. 0:H, 1:W
    nne_activation_param activation;
} nne_conv_param;

typedef struct _nne_pool_param
{
    unsigned int kernel_size[2]; // 0:H, 1:W
    unsigned int stride[2]; // 0:H, 1:W
    unsigned int padding[4]; // 0:left, 1:right, 2:top, 3:bottom
    signed char padding_word;
} nne_pool_param;


/**************************************************************************
  * @brief: Normal conv2d operator
  * @param[in]: conv_param, input_tensor, weight_tensor, bias_tensor
  * @param[out]: output_tensor
  * @return: nne_status
  * @others:
***************************************************************************/
nne_status nne_conv(nne_conv_param conv_param, nne_tensor input_tensor, nne_tensor weight_tensor, nne_tensor bias_tensor, nne_tensor output_tensor);

/**************************************************************************
  * @brief: Depthwise conv2d operator
  * @param[in]: dwconv_param, input_tensor, weight_tensor, bias_tensor
  * @param[out]: output_tensor
  * @return: nne_status
  * @others:
***************************************************************************/
nne_status nne_dwconv(nne_conv_param dwconv_param, nne_tensor input_tensor, nne_tensor weight_tensor, nne_tensor bias_tensor, nne_tensor output_tensor);

/**************************************************************************
  * @brief: Max pooling operator
  * @param[in]: maxpool_param, input_tensor
  * @param[out]: output_tensor
  * @return: nne_status
  * @others:
***************************************************************************/
nne_status nne_maxpool(nne_pool_param maxpool_param, nne_tensor input_tensor, nne_tensor output_tensor);

/**************************************************************************
  * @brief: Average pooling operator
  * @param[in]: avepool_param, input_tensor
  * @param[out]: output_tensor
  * @return: nne_status
  * @others:
***************************************************************************/
nne_status nne_avepool(nne_pool_param avepool_param, nne_tensor input_tensor, nne_tensor output_tensor);

/**************************************************************************
  * @brief: Fully-connected operator
  * @param[in]: activation_param, input_tensor, weight_tensor, bias_tensor, conv_param
  * @param[out]: output_tensor
  * @return: nne_status
  * @others:
***************************************************************************/
nne_status nne_fc(nne_activation_param activation_param, nne_tensor input_tensor, nne_tensor weight_tensor, nne_tensor bias_tensor, nne_tensor output_tensor);

/**************************************************************************
  * @brief: Element-wise add operator
  * @param[in]: input_tensor_1, input_tensor_2
  * @param[out]: output_tensor
  * @return: nne_status
  * @others:
***************************************************************************/
nne_status nne_ew_add(nne_tensor input_tensor_1, nne_tensor input_tensor_2, nne_tensor output_tensor);

/**************************************************************************
  * @brief: Element-wise multiplication operator
  * @param[in]: input_tensor_1, input_tensor_2
  * @param[out]: output_tensor
  * @return: nne_status
  * @others:
***************************************************************************/
nne_status nne_ew_mul(nne_tensor input_tensor_1, nne_tensor input_tensor_2, nne_tensor output_tensor);

#ifdef __cplusplus
} // NNE_RUNTIME extern "C"
#endif

#endif
